package com.aauedu.springboot.config;

import com.aauedu.springboot.bean.Cat;
import com.aauedu.springboot.bean.Dog;
import com.aauedu.springboot.bean.Furn;
import com.aauedu.springboot.bean.Monster;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Scope;

/**
 * 解读
 * 1.@configuration标识这是一个配置类，等价于配置文件
 * 2.程序员可以通过@Bean注解注入bean对象到容器
 * 3.当一个类被@Configuration标识，该类-Bean也会被注入容器
 */

/**
 * 解读
 * 1.proxyBeanMethods：bean的方法
 *  (1)Full(proxyBeanMethods=true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的，是代理方式】
 *  (2)Lite(proxyBeanMethods=False)【每个@Bean方法被调用多少次返回的组件都是新创建的，是非代理模式】
 *  (3)特别说明：proxyBeanMethods是在调用@Bean方法才生效，因此，需要先获取BeanConfig组件，再调用方法
 *  而不是直接通过springboot主程序得到的容器来获取bean，注意观察直接通过ioc.getBean()获取Bean，
 *  proxyBeanMethods值没有生效
 *  (4)如何选择：组件依赖必须使用Full模式默认。如果不需要组件依赖使用Lite模式
 *  (5)Lite模式也称为轻量级模式，因为不检测依赖关系，运行速度快
 */

/**
 * 老韩解读
 * 1.@Import 代码可以看到,可以指定class的数组，可以注入指定类型的Bean
 * public @interface Import  {
 *     Class<?>[] value();
 * }
 * 2.通过@Import方式注入了组件，默认组件名字/id就是对应类型的全类名
 *
 *
 */

//@Configuration(proxyBeanMethods = false)
@Configuration
@Import({Dog.class, Cat.class})
//配置绑定的方式二
/**
 * @EnableConfigurationProperties(Furn.class)解读
 * 1.开启Furn配置绑定功能
 * 2.把Furn组件自动注册到容器中
 */
//@EnableConfigurationProperties(Furn.class)
public class BeanConfig {

    /**
     * 1.@Bean：给容器添加组件，就是Monster Bean
     * 2.monster01():默认你的方法名monster01作为Bean的id
     * 3.Monster：注入类型，注入bean的类型是Monster
     * 4.new Monster(2000, "孙悟空", 10000, "七十二变")注入容器中具体的Bean信息
     * 5.@Bean(name="monster_nmw"):在配置、注入Bean指定名字/id 为monster_nmw
     * 6.默认是单例注入
     * 7.通过@Scope("prototype")可以每次返回新的对象，就是多例.
     * @return
     */
    @Bean
//    @Scope("prototype")
    public Monster monster01() {
        return new Monster(2000, "孙悟空", 10000, "七十二变");
    }


    @Bean(name="monster_nmw")
    public Cat cat01() {
        return new Cat();
    }

    /**
     * 老师解读
     * 1.@ConditionalOnBean(name = "monster_nmw")表示当容器中有一个bean，名字是monster_nmw(类型不做约束)，就注入dog01这个Dog Bean
     * 2.如果没有名字是monster_nmw Bean就不注入dog01这个Dog Bean
     * 3.@ConditionalOnMissingBean(name = "monster_nmw")表示当容器中，没有名字/id为monster_nmw才注入dog01这个bean
     * 4.@ConditionalOnBean(name = "monster_nmw") 也可以放在配置表示对该配置类的所有要注入的组件，都进行条件约束.
     *
     * @return
     */
    @Bean
//    @ConditionalOnBean(name="monster_nmw")
//    @ConditionalOnMissingBean(name = "monster_nmw")
    public Dog dog01() {
        return new Dog();
    }

}
